home *** CD-ROM | disk | FTP | other *** search
- #define __DebugVersion 1
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** RAMInit.c: An INIT which installs DRVR for RamDisk
- **
- ** by Gordon Sheridan and Jim Luther
- ** modified incessantly by Brian Bechtel
- ** and even more so by Quinn "The Eskimo!"
- **
- ** File: RamINIT.c
- **
- ** Copyright © 1992-1996 Apple Computer, Inc.
- ** All rights reserved.
- **
- ** You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours. However, what you are
- ** not permitted to do is to redistribute the source as "DTS Sample Code"
- ** after having made changes. If you're going to re-distribute the source,
- ** we require that you make it clear in the source that the code was
- ** descended from Apple Sample Code, but that you've made changes.
- **
- ** Change History (most recent first):
- **
- ** <1.4> 19970207 Quinn Reworked to use new file layout and bring generally
- ** up-to-date.
- ** <1.4> 19970207 Quinn Rewrote to use TradDriverLoaderLib
- ** Junked some unused prototypes
- ** Renamed RemoveDrive to RemoveDriveFromQueue
- ** <1.3> 08/23/96 BL°B Change dcePtr to dceHandle. Thanks to
- ** Tim Fredenburg for pointing out the error.
- ** <1.3> 06/20/96 BL°B Changes to new routine names
- ** <1.2> 07/03/95 BL°B Many changes for Universal Header 2.0
- ** compliance. Changed how we install driver.
- ** Other bug fixes. See "Changes in 1.2" for
- ** details.
- ** <7> 06/10/94 BL°B Explicitly set zone to system zone before
- ** getting the DRVR resource. Symantec 7.0
- ** doesn't set the System attribute on the DRVR
- ** resource. This can be hard to track down.
- ** <6> 05/19/94 BL°B Modified debugger macros to avoid use of ANSI
- ** routines, and weird c-string dependencies.
- ** <5> 10/15/93 JML Added code to resize unit table if needed.
- ** <4> 10/14/93 JML Implement AddDebuggerLabels routine for MacsBug.
- ** Added Panic debug macros.
- ** <3> 6/29/93 gs Change AddDriveToQueue to start with drive number 5.
- ** <2> 6/28/93 gs Change _DebugVersion to __DebugVersion
- ** <1> 6/13/93 gs Implement AddDebuggerLabels routine for TMON.
- ** <0> 4/17/92 gs Clean up for Sample Code release.
- **/
-
- #ifdef __MWERKS__
- #include <A4Stuff.h>
- #endif
- #ifdef THINK_C
- #include <SetupA4.h>
- #endif
-
- #include <string.h>
- #include <TextUtils.h>
- #include <QuickDraw.h>
- #include <Traps.h>
- #include <Gestalt.h>
- #include <Memory.h>
- #include <Resources.h>
- #include <DiskInit.h>
-
- #include "RamDiskCommon.h"
- #include "TradDriverLoaderLib.h"
- #include "ShowInitIcon.h"
-
- ///////////////////////////////////////////////////////////////////////////
-
- #define kDriverName "\p.RamDRVR"
-
- enum {
- kMinUnitNum = 48 /* the lowest unit number we can use */
- };
-
- ///////////////////////////////////////////////////////////////////////////
- //
- // Custom drive queue element. Normally you might to extend this to have
- // extra drive-specific variables, but in this case we have no extra
- // variables. Still, we define our own structure rather than use
- // the one in <Files.h> because our structure has the magic "flags"
- // field at the front.
-
- struct MyDrvQEl
- {
- long flags;
- QElemPtr qLink;
- short qType;
- short dQDrive;
- short dQRefNum;
- short dQFSID;
- unsigned short dQDrvSz;
- unsigned short dQDrvSz2;
- };
- typedef struct MyDrvQEl MyDrvQEl;
- typedef MyDrvQEl *MyDrvQElPtr;
-
- ///////////////////////////////////////////////////////////////////////////
-
- enum {
- // ICN#
- rLoadOKIcon = -4064, /* same as cdev icon */
- rLoadBadIcon = -4033,
- rPhysicalIcon = -4034,
- rMediaIcon = -4035
- };
-
- ///////////////////////////////////////////////////////////////////////////
-
- static OSErr InitializeGlobals (DrvrGlobals *driverGlobals)
- // Initialize the globals using data read from resources.
- {
- OSErr result = -1;
- Handle physicalIconHandle;
- Handle mediaIconHandle;
- VersRecHndl versionHandle;
- ConfigRecHandle configHandle;
- long length;
-
- driverGlobals->ramDisk = nil; /* RAM disk memory isn't allocated yet */
-
- /* Get the user configuration, icons, and the "where" string */
- configHandle = (ConfigRecHandle)Get1Resource ('RDcf', rConfiguration);
- physicalIconHandle = Get1Resource('ICN#', rPhysicalIcon);
- mediaIconHandle = Get1Resource('ICN#', rMediaIcon);
-
- versionHandle = (VersRecHndl) Get1Resource('vers', 1);
-
- if (configHandle && physicalIconHandle && mediaIconHandle && versionHandle)
- {
- /* See if we are supposed to install */
- if ((**configHandle).install)
- {
- /* Copy the user's preferred volume name to the driver globals. */
- length = (**configHandle).volumeName[0]+1;
- BlockMoveData((**configHandle).volumeName, driverGlobals->volumeName, length);
-
- /* Copy ICN# to driver globals so it has a physical location icon for volumes. */
- BlockMoveData( &(**physicalIconHandle), (Ptr)(driverGlobals->physicalIcon), kLargeIconSize);
-
- /* Copy ICN# to driver globals so it has a default media icon for volumes. */
- BlockMoveData( &(**mediaIconHandle), (Ptr)(driverGlobals->mediaIcon), kLargeIconSize);
-
- /* Put the drive location string into the driver globals. */
- GetIndString(driverGlobals->locationStr, rStringList, strLocationStr);
- if (ResError() != noErr)
- BlockMoveData("\pIn RAM", driverGlobals->locationStr, 7);
-
- driverGlobals->ramSize = (**configHandle).size * 1024;
-
- driverGlobals->driverVersion = (**versionHandle).numericVersion;
-
- result = noErr;
- }
- }
-
- if (configHandle)
- ReleaseResource((Handle)configHandle);
- else
- Panic("\pYou forgot to turn settings on in control panel");
- if (physicalIconHandle)
- ReleaseResource(physicalIconHandle);
- if (mediaIconHandle)
- ReleaseResource(mediaIconHandle);
-
- return (result);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- static OSErr AddDriveToQueue (long size, short drvrRef, short *driveNum)
- // Find the first unused drive number greater than 4, allocate and initialize
- // a drive queue element (including the drive flags), and add the drive queue
- // element to the drive queue.
- {
- OSErr result = noErr;
- QHdrPtr driveQHdr;
- DrvQEl *drivePtr;
- MyDrvQElPtr newDrivePtr;
- Boolean driveNumFound = false;
-
-
- driveQHdr = GetDrvQHdr();
-
- /* find first free drive number */
- *driveNum = 5; /* drive numbers 1-4 are reserved */
- while (! driveNumFound)
- {
- drivePtr = (DrvQEl *)driveQHdr->qHead; /* get first drive */
- while (drivePtr && *driveNum != drivePtr->dQDrive) /* order of tests important! */
- drivePtr = (DrvQEl *)drivePtr->qLink; /* get next drive */
-
- if (drivePtr == nil)
- driveNumFound = true;
- else
- ++(*driveNum);
- }
-
- if (*driveNum > 0) /* must be a positive short */
- {
- /* allocate new drive queue element */
- newDrivePtr = (MyDrvQElPtr)NewPtrSysClear(sizeof(MyDrvQEl));
- if (newDrivePtr != nil)
- {
- newDrivePtr->flags = 0x00080000; /* non-ejectable, disk not locked */
- newDrivePtr->qType = 1; /* see IM vol.4 p.181 */
- newDrivePtr->dQDrive = *driveNum; /* •• dQDrive and dQRefNum are filled */
- newDrivePtr->dQRefNum = drvrRef; /* •• in by AddDrive */
- newDrivePtr->dQFSID = 0; /* HFS */
- newDrivePtr->dQDrvSz = size & 0x0000FFFF; /* dQDrvSz = LoWord of size */
- newDrivePtr->dQDrvSz2 = size >> 16; /* dQDrvSz2 = HiWord of size */
-
- AddDrive (drvrRef, *driveNum, (DrvQEl *)&newDrivePtr->qLink);
- }
- else
- result = memFullErr;
- }
- else
- /* more than 32768 drives!?! */
- result = nsDrvErr;
-
- return (result);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- static OSErr RemoveDriveFromQueue (short driveNum, DrvQElPtr *drivePtr)
- // Find the drive queue element for driveNum in the drive queue and Dequeue it.
- // Return pointer to the drive queue element removed in *drivePtr.
- {
- QHdrPtr driveQHdr;
-
- driveQHdr = GetDrvQHdr();
- *drivePtr = (DrvQEl *)driveQHdr->qHead; /* get first drive */
- while (*drivePtr && (driveNum != (*drivePtr)->dQDrive)) /* order of tests important! */
- *drivePtr = (DrvQEl *)(*drivePtr)->qLink; /* get next drive */
-
- if (*drivePtr != nil)
- return (Dequeue((QElemPtr)*drivePtr, driveQHdr));
- else
- return (nsDrvErr);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- static short NumToolboxTraps (void)
- {
- if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap) )
- return (0x200);
- else
- return (0x400);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- static TrapType GetTrapType (short theTrap)
- {
- if (theTrap & 0x0800)
- return (ToolTrap);
- else
- return (OSTrap);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- static Boolean TrapAvailable (short theTrap)
- {
- TrapType tType;
-
- tType = GetTrapType(theTrap);
- if (tType == ToolTrap)
- {
- theTrap = theTrap & 0x7FF;
- if (theTrap >= NumToolboxTraps() )
- theTrap = _Unimplemented;
- }
-
- return (NGetTrapAddress(theTrap, tType) !=
- NGetTrapAddress(_Unimplemented, ToolTrap) );
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- #define kMacsbugMacroStr "\p;MC RamDisk 'DM #"
- #define kMacsbugMacroStr2 "\p';g"
-
- #define kTMONMacroStr "\p™AddLabel RamDisk,."
- #define kTMONMacroStr2 "\p,."
-
- #define AddString(src, dst) { BlockMoveData(&src[1], dst+i, src[0]); i += src[0]; }
-
- static void AddDebuggerLabels (DrvrGlobals driverGlobals)
- // Add TMON or MacsBug debugger macros for easy viewing of RamDisk
- {
- Str255 strbuf = "\p";
- Str31 numstr;
- long tmonVal;
- short err;
- Boolean done = false;
- SignedByte debugFlags;
- short i;
-
- if (TrapAvailable(_Gestalt)) /* check for TMON */
- {
- err = Gestalt('TMON',&tmonVal);
- if (err == 0)
- {
- /* Add TMON label */
- i = 1;
- AddString(kTMONMacroStr, strbuf);
- NumToString((long)driverGlobals.ramDisk,numstr);
- AddString(numstr, strbuf);
- AddString(kTMONMacroStr2, strbuf);
- NumToString(driverGlobals.ramSize,numstr);
- AddString(numstr, strbuf);
- strbuf[0] = i - 1;
-
- DebugStr(strbuf);
-
- done = true;
- }
- }
- if (!done) /* If TMON isn't installed, define a macro for MacsBug */
- {
- debugFlags = *(SignedByte *) 0x0BFF; // MacJmpFlag
- if (debugFlags == -1)
- debugFlags = *(SignedByte *) 0x0120; // MacJmp
-
- if (debugFlags & 0x20)
- {
- /* Define MacsBug macro */
- i = 1;
-
- AddString(kMacsbugMacroStr, strbuf);
- NumToString((long)driverGlobals.ramDisk, numstr);
- AddString(numstr, strbuf);
- AddString(kMacsbugMacroStr2, strbuf);
- strbuf[0] = i - 1;
-
- DebugStr(strbuf);
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- void main (void)
- {
- DrvrGlobals driverGlobals;
- short csParam[11];
- short drvrRefNum = 0;
- short driveNum = 0;
- DrvQElPtr driveQElPtr;
- OSErr result;
- DCtlHandle dceHandle;
- Boolean driverInstalled = false;
-
- #ifdef THINK_C
- RememberA0();
- SetUpA4();
- #endif
- #ifdef __MWERKS__
- long oldA4 = SetCurrentA4();
- #endif
-
- Panic("\pStarting RAMDisk");
- ShowInitIcon(rLoadOKIcon,false); /* show OK icon to indicate we're executing */
-
- result = InitializeGlobals(&driverGlobals);
- if (result != noErr)
- {
- Panic("\pCould not initialize globals");
- goto Done;
- }
-
- driverGlobals.ramDisk = NewPtrSysClear(driverGlobals.ramSize);
- if (driverGlobals.ramDisk == nil)
- {
- Panic("\pNewSysPtr = nil");
- result = memFullErr;
- goto Done;
- }
-
- #if __DebugVersion
- AddDebuggerLabels(driverGlobals);
- #endif __DebugVersion
-
- // <1.4>
- result = TradInstallDriverFromResource(0, kDriverName,
- kMinUnitNum,
- TradHighestUnitNumber() + 1,
- &drvrRefNum);
- if (result == noErr || result == dupFNErr) {
- driverInstalled = (result == noErr);
- result = TradOpenInstalledDriver(drvrRefNum, fsRdWrPerm);
- } else {
- Panic("\pTradInstallDriverFromResource failed!");
- goto Done;
- }
-
- if (result != noErr)
- {
- Panic("\pTradOpenInstalledDriver failed");
- goto Done;
- }
-
- /* put in drive queue */
- result = AddDriveToQueue (driverGlobals.ramSize / 512, drvrRefNum, &driveNum);
- if (result != noErr)
- {
- Panic("\pAddMyDrive returned negative driveNum!");
- goto Done;
- }
- /* driveNum now = drive number */
-
- /* Save driveNum in our globals so driver code can verify drive number in
- Prime, Status and Control calls (if need be). The driver also checks
- driveNum in the driver globals for a non-zero value before accepting
- regular prime, control and status calls.
- */
- driverGlobals.driveNumber = driveNum;
-
- /* set drivers globals */
- *(Ptr *)csParam = (Ptr)&driverGlobals;
- result = Control(drvrRefNum, setGlobalsCC, (Ptr)csParam);
- if (result != noErr)
- {
- Panic("\pControl returned err");
- goto Done;
- }
-
- /* check to see if it got them */
- result = Status(drvrRefNum, getGlobalsSC, (Ptr)csParam);
- if ((result != noErr) || (driverGlobals.ramSize != *(long *)csParam))
- {
- Panic("\pStatus returned err");
- goto Done;
- }
-
- /* zero & mount */
- result = DIZero(driveNum, driverGlobals.volumeName);
- if (result != noErr)
- {
- Panic("\pDIZero returned err");
- goto Done;
- }
-
- Done:
- if (result == noErr)
- ShowInitIcon(rLoadOKIcon,true); /* draw OK icon and move pen */
- else
- {
- dceHandle = GetDCtlEntry(drvrRefNum);
- if (dceHandle != nil)
- if ((**dceHandle).dCtlFlags & dOpenedMask)
- {
- /* Driver is open - close it */
- result = CloseDriver(drvrRefNum);
- if (result == noErr)
- /* If driver was closed, ramDisk memory was released! */
- driverGlobals.ramDisk = nil;
- }
-
- if (driveNum != 0)
- {
- result = RemoveDriveFromQueue(driveNum, &driveQElPtr); /* ignore errors */
- if (result == noErr)
- /* Dispose of the DrvQEl. Since it was allocated as a
- MyDrvQEl record, we have to subract 4 from the address */
- DisposePtr((Ptr)((Ptr)(driveQElPtr) - 4));
- }
-
- // <1.4>
- if (driverInstalled) {
- (void) TradRemoveDriver(drvrRefNum, false);
- }
-
- if (driverGlobals.ramDisk != nil)
- DisposePtr(driverGlobals.ramDisk);
-
- #if __DebugVersion
- /* ••• Need to add routine to remove TMON/MacsBug debugging macros */
- #endif __DebugVersion
-
- ShowInitIcon(rLoadBadIcon,true); /* draw bad load icon and move pen */
- }
- #ifdef THINK_C
- RestoreA4();
- #endif
- #ifdef __MWERKS__
- SetA4(oldA4);
- #endif
- }
-